﻿using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using NewRetail.Application.Components.Platform.Entity;
using NewRetail.Application.Core;
using System;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Uow;

namespace NewRetail.Application.Components.Platform
{
    public class GetPosIntegralUsageRuleDto : EntityDto
    {
        public DateTime? UpdateTime { get; set; }
        public int? Page { get; set; }
    }
    public class MemberIntegralUsageAmountDto
    {
        /// <summary>
        /// 会员Id
        /// </summary>
        public string memberId { get; set; }
        /// <summary>
        /// POS订单支付金额
        /// </summary>
        public decimal posOrderAmount { get; set; }
        /// <summary>
        /// 备注说明
        /// </summary>
        public string remark { get; set; }
    }
    public class MemberIntegralUsageAmountResponseDto
    {
        /// <summary>
        /// 可抵现金
        /// </summary>
        public decimal availableRedemptionAmount { get; set; }
        /// <summary>
        /// 使用积分
        /// </summary>
        public decimal useIntegral { get; set; }
    }


    public interface IPosIntegralUsageRuleService : IApplicationService
    {
        Task<PosIntegralUsageRule[]> AttachWarehouse(PosIntegralUsageRule[] data);
        /// <summary>
        ///  根据会员、兑换金额计算出可使用积分（积分抵现）
        /// </summary>
        /// <param name="inputDto"></param>
        /// <returns></returns>
        Task<(decimal, decimal, string)> PosMemberIntegralUsageAmount(MemberIntegralUsageAmountDto inputDto);
    }

    public class PosIntegralUsageRuleService : MyApplicationService, IPosIntegralUsageRuleService
    {
        private readonly ILogger _logger;
        private readonly IRepository<PosIntegralUsageRule> _posIntegralUsageRule;

        public PosIntegralUsageRuleService(IRepository<PosIntegralUsageRule> posIntegralUsageRule, ILogger<PosIntegralUsageRuleService> logger)
        {
            this._posIntegralUsageRule = posIntegralUsageRule;
            _logger = logger;
        }

        public async Task<PosIntegralUsageRule[]> AttachWarehouse(PosIntegralUsageRule[] data)
        {
            var db = await this._posIntegralUsageRule.GetDbContextAsync();

            await db.AttachData<Warehouse.Entity.Warehouse, PosIntegralUsageRule>(
                data, idGetter: x => x.warehouseID, action: (m, arr) =>
                {
                    m.Warehouse = arr.FirstOrDefault();
                });

            return data;
        }

        #region 根据会员、兑换金额计算出可使用积分（积分抵现）
        /// <summary>
        ///  根据会员、兑换金额计算出可使用积分（积分抵现）
        /// </summary>
        /// <param name="inputDto"></param>
        /// <returns></returns>
        public async Task<(decimal, decimal, string)> PosMemberIntegralUsageAmount(MemberIntegralUsageAmountDto inputDto)
        {
            using var uow = this.UnitOfWorkManager.Begin(requiresNew: true);
            var db = await this._posIntegralUsageRule.GetDbContextAsync();
            try
            {
                var memberId = inputDto.memberId;
                //获取会员信息
                var posMember = await db.Set<PosMember>().Where(x => x.Id == memberId).FirstOrDefaultAsync();
                if (object.Equals(posMember, null))
                    return (0, 0, "会员不存在！");
                //积分抵现规则
                var posIntegralUsageRuleData = await db.Set<PosIntegralUsageRule>().Where(x => x.isAuditing == true).OrderByDescending(o => o.addTime).FirstOrDefaultAsync();
                if (object.Equals(posIntegralUsageRuleData, null))
                    return (0, 0, "抵现规则不存在或未启用,无法抵现！");
                //当前会员可用积分
                var curAvailableIntegral = posMember.integral;
                if (curAvailableIntegral <= 0)
                    return (0, 0, "会员积分不足！");

                //兑换所需积分
                var usageIntegral = posIntegralUsageRuleData.usageIntegral;
                if (curAvailableIntegral < usageIntegral)
                    return (0, 0, "会员积分不足最小抵扣积分！");

                //兑换金额
                var exchangeAmount = posIntegralUsageRuleData.exchangeAmount;
                //是否启用金额门槛
                var isEnabledAmouontThreshold = posIntegralUsageRuleData.isEnabledAmouontThreshold;
                //金额门槛（值为百分比）
                var amountThreshold = posIntegralUsageRuleData.amountThreshold;
                var payAmount = inputDto.posOrderAmount;
                //可抵现金额。相除后进行向下取整（即直接丢弃小数部分）
                var availableRedemptionAmount = Math.Floor(Decimal.Divide(curAvailableIntegral * exchangeAmount, usageIntegral));
                //启用了金额门槛，那么需要计算实际抵扣的最大现金
                if (isEnabledAmouontThreshold)
                    payAmount = Math.Floor(Decimal.Divide(payAmount * amountThreshold, 100M));
                else
                    payAmount = Math.Floor(payAmount);
                //使用积分
                var useIntegral = 0;
                //可抵现金额大于等于实际抵现支付金额，那么使用积分根据实际抵现支付金额使用，否则根据可抵现金额使用
                if (availableRedemptionAmount >= payAmount)
                    useIntegral = (int)(payAmount * exchangeAmount * usageIntegral);
                else
                    useIntegral= (int)(availableRedemptionAmount * exchangeAmount * usageIntegral);

                availableRedemptionAmount = Math.Floor(Decimal.Divide(useIntegral * exchangeAmount, usageIntegral));
                //是否启用每单抵扣金额上限
                var isEnabledUpperLimitAmouont = posIntegralUsageRuleData.isEnabledUpperLimitAmouont;
                //如果启用每单抵扣金额上限，那需要继续计算
                if (isEnabledUpperLimitAmouont)
                {
                    var upperLimitAmount = posIntegralUsageRuleData.upperLimitAmount;
                    if (availableRedemptionAmount > upperLimitAmount)
                    {
                        //比单笔抵扣金额大，那么只能使用最大抵扣金额
                        availableRedemptionAmount = upperLimitAmount;
                        useIntegral = (int)(upperLimitAmount * exchangeAmount * usageIntegral);
                    }
                }

                //this.EntityHelper.InitEntity(memberIntegral);
                //await _posIntegralRep.InsertAsync(memberIntegral);

                //await uow.CompleteAsync();
                ////发送通知来处理会员积分，通知订阅。实际就是调用MemberIntegralWorker的订阅OnMessage方法
                //var svc = this.LazyServiceProvider.LazyGetRequiredService<IDataSyncService>();
                //var mbIntegralArr = new List<PosIntegral>();
                //mbIntegralArr.Add(memberIntegral);
                //await svc.QueueDataSync(mbIntegralArr.ToArray());

                return (availableRedemptionAmount, useIntegral, "");
            }
            catch (Exception e)
            {
                await uow.RollbackAsync();
                _logger.LogError(message: e.Message, exception: e);
                return (0, 0, e.Message);
            }
        }
        #endregion
    }
}
